home *** CD-ROM | disk | FTP | other *** search
/ Sky at Night 2005 September / SAN CD 9-2005 non bonus CD-ROM 4.iso / pc / software / SkyMap / skymap.exe / QSORT.PRN < prev    next >
Encoding:
Text File  |  1988-07-11  |  64.9 KB  |  1,519 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.                                        
  23.  
  24.  
  25.                                        
  26.  
  27.  
  28.                              QSORT -- Version 3.20
  29.                                        
  30.                            Text File Sorting Utility
  31.                                        
  32.                                        
  33.                                        
  34.                                        
  35.                                        
  36.                                        
  37.                                        
  38.                                        
  39.                                        
  40.                                        
  41.  
  42.  
  43.                     Copyright 1985, 86, 87, 88 - Ben Baker
  44.                                        
  45.                               All rights reserved
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.                                Table of Contents
  74.  
  75.  
  76.  
  77.        Introduction                                                    1
  78.           Notation                                                     1
  79.  
  80.        The QSORT Command and Options                                   2
  81.           The /<key_spec> Parameter                                    2
  82.           The /F<len> Parameter                                        3
  83.           The /T[<tag>] Parameter                                      4
  84.           The /D[<fields>][<delim>[<term>]] Parameter                  4
  85.           The /R Parameter                                             6
  86.           The /S[V] Parameter                                          6
  87.           The /? Parameter                                             7
  88.  
  89.        Lexical Sorting                                                 8
  90.  
  91.        Examples                                                       10
  92.  
  93.        Error Messages and Return Codes                                12
  94.           Command Line Errors                                         12
  95.           Memory Errors                                               14
  96.           I/O Errors                                                  14
  97.           Internal Errors                                             15
  98.           ERRORLEVEL Return Codes                                     15
  99.  
  100.        Implementation Notes                                           16
  101.           General Information                                         16
  102.           Performance and DOS Configuration                           16
  103.           Performance and Input Record Type                           19
  104.           Performance and Sort Keys                                   19
  105.           Performance and File Size                                   20
  106.  
  107.        About Shareware                                                21
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.                                         i
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.  
  142.                                  Introduction
  143.                                  Introduction
  144.  
  145.  
  146.        QSORT was first designed to be a replacement for, and to overcome
  147.        the limitations  of DOS  SORT, but  has been enhanced a number of
  148.        times and moved to new compilers twice.  The current version will
  149.        sort files  whose size  is limited  only by available disk space.
  150.        File name(s)  may be  given explicitly  or QSORT  will sort  from
  151.        standard input  to standard  output, and so, may be used in pipes
  152.        or with  redirection.   Multiple keys  may be  specified.  Binary
  153.        files with fixed-length records may be sorted, provided only that
  154.        keys are ASCII character strings.
  155.  
  156.        QSORT tries  to be very protective of your data.  If QSORT has an
  157.        error of  any kind,  it will  terminate with the input file still
  158.        intact, and  will return to DOS with a non-zero ERRORLEVEL.  When |
  159.        QSORT successfully completes a sorting a file, it terminates with |
  160.        ERRORLEVEL set to zero.                                           |
  161.  
  162.        The command line syntax is a super-set of SORT's, so QSORT may be
  163.        used without other changes in batch files using SORT, but in most
  164.        cases you will probably want to make use of QSORT's greater capa-
  165.        bilities.
  166.  
  167.        Notation
  168.        Notation
  169.  
  170.        In defining  the command  line and  its various  parameters,  the
  171.        following notation is used:
  172.  
  173.        [optional] items are enclosed in square brackets.
  174.        [optional]
  175.  
  176.        <variable> items  appear in  lower case  and are enclosed in
  177.        <variable>
  178.             angle brackets.   They are replaced by actual data such
  179.             as a file name.  The angle brackets are NOT typed.
  180.  
  181.        THIS |  THAT   Choices are  separated  by  a  vertical  bar.
  182.        THIS |  THAT
  183.             Select one or the other but not both.
  184.  
  185.        [THIS |  THAT]   When the  choices are  enclosed  in  square
  186.        [THIS |  THAT]
  187.             brackets, you may also select neither.
  188.  
  189.        REPEAT. . .  The ellipsis (. . .) means the item to its left
  190.        REPEAT. . .
  191.             may be repeated as many times as necessary.
  192.  
  193.        UPPER CASE  items and  all special  characters  not  defined
  194.        UPPER CASE
  195.             above represent  themselves.   They are entered exactly
  196.             as they appear.
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.        QSORT Text Sorting Utility                                 Page 2
  211.        QSORT Text Sorting Utility                                 Page 2
  212.  
  213.  
  214.                          The QSORT Command and Options
  215.                          The QSORT Command and Options
  216.  
  217.  
  218.        QSORT is invoked with the following command:
  219.  
  220.             QSORT [<in_file> [<out_file>]] [/<key_spec>. . .]
  221.             QSORT [<in_file> [<out_file>]] [/<key_spec>. . .]
  222.                  [/F<len> | /T[<tag> | /D[[<fields>][<delim>[<term>]]]
  223.                  [/F<len> | /T[<tag> | /D[[<fields>][<delim>[<term>]]]
  224.                  [/R] [/S[V]] [/?]                                       |
  225.                  [/R] [/S[V]] [/?]
  226.  
  227.        Note that  all parameters  on the command line are optional.  The
  228.        <in_file> and  <out_file> parameters  are "ASCII-Z"  file  speci-
  229.        fiers.   They may  contain disk and path information in the stan-
  230.        dard DOS format, but must not contain "wild-card" characters.  If
  231.        <in_file> is missing, QSORT sorts from standard input to standard
  232.        output.   These are  files defined and opened by DOS before QSORT
  233.        is loaded.   (See  your DOS manual concerning the use of redirec-
  234.        tion and pipes.)
  235.  
  236.        If <in_file>  is given but <out_file> is missing, QSORT creates a
  237.        temporary file in the directory containing <in_file> and sorts to
  238.        the temporary  file.   On  successful  completion  of  the  sort,
  239.        <in_file> is  deleted and  the temporary is renamed to <in_file>.
  240.        The effect is an apparent "sort-in-place."
  241.  
  242.        If both  file names  are given,  <in_file> is  unchanged and  the
  243.        sorted output  is written to <out_file>.  Note that the following
  244.        two commands are exactly equivalent:
  245.  
  246.             QSORT  FILE.TXT  FILE.SRT
  247.             QSORT  FILE.TXT  FILE.SRT
  248.  
  249.             QSORT <FILE.TXT >FILE.SRT
  250.             QSORT <FILE.TXT >FILE.SRT
  251.  
  252.        In the  first, QSORT opens the files.  In the second, redirection
  253.        is specified  and DOS  opens the  files.  The result is the same.
  254.        It is  an error  QSORT can't  detect if  you mix  these.  For in-
  255.        stance:
  256.  
  257.             QSORT  FILE.TXT >FILE.SRT
  258.             QSORT  FILE.TXT >FILE.SRT
  259.  
  260.        will result  in a  sort-in-place.   QSORT will  open FILE.TXT but
  261.        won't know DOS has opened FILE.SRT for it, and will ignore it.
  262.  
  263.        The /<key_spec> Parameter
  264.        The /<key_spec> Parameter
  265.  
  266.        Up to  30 /<key_spec> parameters may be used to specify sort keys
  267.        and are  ordered  major  to  minor  from  left  to  right.    The
  268.        /<key_spec> argument has the form:
  269.  
  270.             /[L][+|-][<field>.][<col>][:<length>]
  271.             /[L][+|-][<field>.][<col>][:<length>]
  272.  
  273.        Note that  all elements  of this  argument are "optional," but at
  274.        least one element must be present following the slant-bar (/).
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.        QSORT Text Sorting Utility                                 Page 3
  287.        QSORT Text Sorting Utility                                 Page 3
  288.  
  289.  
  290.        The 'L',  if present,  specifies "lexical" sequence for this key.
  291.        Lexical sequence  is ordered  first by  spelling, then, when keys
  292.        have identical spelling, by capitalization.
  293.  
  294.        The minus (-) sign reverses the sorting order for this key, while
  295.        the plus (+) sign (or no sign) specifies normal sort order.
  296.  
  297.        There are three numbers associated with every sort key; the field
  298.        number, the  starting column  within the field, and the length of
  299.        the key  in characters.   Any,  or all  of them may be given in a
  300.        /<key_spec> parameter.   QSORT  uses punctuation to identify each
  301.        number.   A number followed by a period (.) is a field number.  A
  302.        number preceded by a colon (:) is a length number.  A column num-
  303.        ber has  no punctuation associated with it.  It follows the field
  304.        number, if any, and precedes the length number, if any.
  305.  
  306.        The  [<field.>]   element  is  used  only  for  "delimited-field"
  307.        records, and  locates this  key within  a particular  field.  The
  308.        value of  <field.> must  be less  than or  equal to the number of
  309.        fields defined  with the /D parameter (see below).  If [<field>.]
  310.        is omitted  when sorting delimited-field records, the first field
  311.        is assumed.   For  consistency, all  records are  assumed to have
  312.        "fields."   In all cases except delimited-field records, there is
  313.        precisely one field, and it spans the entire record.
  314.  
  315.        If present,  [<col>] defines the beginning column of the key.  If
  316.        omitted, column  1 is  assumed.   In the  case of delimited-field
  317.        records, column 1 is the first character of the identified field.
  318.        In all  other cases,  column 1  is the  first  character  of  the
  319.        record.
  320.  
  321.        If present,  [:<length>] defines  the key  length in  columns (or
  322.        characters).   If [:<length>] is omitted, the rest of the record,
  323.        or field in delimited-field records, is assumed to be part of the
  324.        key.
  325.  
  326.        If no  key parameters are given, the entire record, or the entire
  327.        first field is the key.
  328.  
  329.        When sorting variable-length records, any key which begins beyond
  330.        the end  of its field in a particular record is treated as a null
  331.        (zero length)  key for that record, and will sort low relative to
  332.        all records  with non-null  values for  that key.   When  sorting
  333.        fixed-length records,  all defined  keys must fall within the de-
  334.        fined record  length.  <key_spec> parameters must appear in order
  335.        of importance, primary key first.
  336.  
  337.        The /F<len> Parameter
  338.        The /F<len> Parameter
  339.  
  340.        The /F<len>  parameter denotes  the record  length for  a file of
  341.        fixed-length records.   All records in the input file MUST be ex-
  342.        actly <len> bytes long.  The records need not (but may) be termi-
  343.        nated with a CR/LF sequence.  They may contain any data, even bi-
  344.        nary data,  but the  keys must  be ASCII strings.  Strings may be
  345.  
  346.  
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.        QSORT Text Sorting Utility                                 Page 4
  355.        QSORT Text Sorting Utility                                 Page 4
  356.  
  357.  
  358.        terminated with  a null (binary zero) character, or may be padded
  359.        with trailing spaces to the full length of the key.
  360.  
  361.        Note that QSORT does not attempt to support Pascal style strings.
  362.        These are strings which begin with a character whose binary value
  363.        is a  character count.  This is followed by <count> characters of
  364.        ASCII data,  which in  turn is followed by random data out to the
  365.        maximum length of the string.  These strings may be used as keys,
  366.        but the  programmer must insure that either the last real charac-
  367.        ter is  a null character, or the key is padded to its full length
  368.        with spaces.   QSORT must be told that the key begins in the sec-
  369.        ond character position (the first character of real data).
  370.  
  371.        The /T[<tag>] Parameter
  372.        The /T[<tag>] Parameter
  373.  
  374.        The /T[<tag>] parameter, if present, indicates that the "records"
  375.        to be sorted may be more than a single line long.
  376.  
  377.        If <tag>  is also  present, it  defines a character to be used to
  378.        tag the  "end-of-record."   If <tag>  is not  present, the  first
  379.        empty line  terminates the  record.   For this  purpose,  "empty"
  380.        means "no  characters." A  line containing  but a single space is
  381.        NOT empty!  A line may be "tagged" by placing the <tag> character
  382.        anywhere on  the last line of a logical record.  The entire line,
  383.        including the  tag character  will appear as the last line of the
  384.        record.
  385.  
  386.        Some characters  cannot be  used to represent themselves in a DOS
  387.        command line.   For  that reason,  QSORT uses  codes to represent
  388.        them.   These codes are actually a pair of characters.  The first
  389.        is always  a back-slash (\).  The second character identifies the
  390.        special character  it represents.   The  following is  a table of
  391.        characters recognized by QSORT:
  392.  
  393.                \B - Space character     20 Hex     32 Decimal
  394.                \F - Form feed character 0C         12
  395.                \L - Line feed character 0A         10
  396.                \N - Newline sequence
  397.                \R - Carriage return     0D         13
  398.                \T - Tab character       09          9
  399.                \\ - Back-slash character itself
  400.  
  401.        Thus an invisible tab character might be used to end a multi-line
  402.        logical record.   The  other characters  in this  code list don't
  403.        make much  sense in  this context,  but will  be useful in the /D
  404.        parameter (see below).
  405.  
  406.        Note that  the /F<len> and /T[<tag>] parameters are incompatible,
  407.        and may not both be specified.
  408.  
  409.        The /D[<fields>][<delim>[<term>]] Parameter
  410.        The /D[<fields>][<delim>[<term>]] Parameter
  411.  
  412.        The /D[<fields>][<delim>[<term>]]  parameter, if  present, states
  413.        that this file contains delimited-field records.  In other words,
  414.  
  415.  
  416.  
  417.  
  418.  
  419.  
  420.  
  421.  
  422.  
  423.        QSORT Text Sorting Utility                                 Page 5
  424.        QSORT Text Sorting Utility                                 Page 5
  425.  
  426.  
  427.        a record is made up of distinct, variable length fields separated
  428.        from one  another by  a  particular  character,  or  "delimiter."
  429.        Records are separated, or "delimited" by the "newline sequence."
  430.  
  431.        The <fields> element defines the number of variable length fields
  432.        contained in each record.  All fields must be present in each and
  433.        every record.   A "null" field will be represented by two succes-
  434.        sive delimiter characters.  There must always be exactly <fields>
  435.        minus 1 delimiter characters in a record.
  436.  
  437.        If a  <delim> character  is present, QSORT uses it as a field de-
  438.        limiter character.   Otherwise  a comma  (,) is assumed to be the
  439.        delimiter.
  440.  
  441.        If a  <term> character is also present, QSORT uses it as a record
  442.        delimiter  character.    In  fact,  it  literally  redefines  the
  443.        "newline sequence" to QSORT.  More on this in a moment.
  444.  
  445.        The same  character codes  listed under  the /T  parameter may be
  446.        used to  represent these  characters.   Note that  "\N" means the
  447.        "newline sequence."   If <term> is not present, this is the CR-LF
  448.        character pair.   If  <term> is present, it represents the <term>
  449.        character.  Thus:
  450.  
  451.             /D3\N\T
  452.             /D3\N\T
  453.  
  454.        says that  the records  are separated by tab characters, and that
  455.        the three  fields within  each record  are also  separated by tab
  456.        characters.  On the other hand:
  457.  
  458.             /D3\N
  459.             /D3\N
  460.  
  461.        says that  each group  of three  lines  constitutes  one  logical
  462.        record, and each line is a field within that record.
  463.  
  464.        The /D  parameter is  always incompatible  with the /F parameter,
  465.        and usually  incompatible with  the /T parameter, but there is an
  466.        exception when <fields> is missing, or is equal to 1.
  467.  
  468.        If <fields>  equals 1  (or is missing) it says that there is only
  469.        one field spanning the entire record.  But that is what QSORT as-
  470.        sumes if the whole /D parameter is missing!  So why bother?
  471.  
  472.        In most  ASCII files a "line" ends with a carriage return charac-
  473.        ter (CR)  followed by a line feed character (LF).  QSORT searches
  474.        for this  character pair  when it  is looking  for a "newline se-
  475.        quence."
  476.  
  477.        But not  all files use CR-LF as a line terminator.  For instance,
  478.        files imported  from UNIX or XENIX usually terminate lines with a
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.        QSORT Text Sorting Utility                                 Page 6
  493.        QSORT Text Sorting Utility                                 Page 6
  494.  
  495.  
  496.        naked line  feed character!  And some editors produce files whose
  497.        lines end in a naked carriage return character!  So:
  498.  
  499.             /D,\L
  500.             /D,\L
  501.  
  502.        says "for  this file,  the newline sequence is a single line feed
  503.        character."   In this  case, the  comma is a place holder.  There
  504.        really is  no "delimiter  character," but  one must be present in
  505.        the parameter in order to define the <term> character.
  506.  
  507.        The /R Parameter
  508.        The /R Parameter
  509.  
  510.        The /R  parameter is included for compatibility with DOS SORT and
  511.        is redundant.   It  reverses the  sense of sort direction for all
  512.        sort keys.
  513.  
  514.        The /S[V] Parameter                                               |
  515.        The /S[V] Parameter
  516.  
  517.        The /S  parameter tells  QSORT to make a statistics report to the
  518.        screen at  the end  of a  run.   The report  is  written  to  the
  519.        "standard error"  device, the console, and may not be redirected.
  520.        The following  is an  actual statistics  report  "cut"  from  the
  521.        screen after QSORT had sorted a 1.3+ megabyte file:
  522.  
  523.        -----------------------------------------------------------------
  524.        QSORT - Text Sort - Version 3.20                                  |
  525.        Copyright (c) 1985, 1986, 1987  - Ben Baker - All rights reserved
  526.  
  527.             12115 records sorted
  528.               150 bytes in longest record
  529.  
  530.            127131 sort phase comparisons
  531.             73232 merge phase comparisons
  532.  
  533.            200363 total comparisons
  534.              16.5 comparisons per input record
  535.  
  536.                27 temporary merge files created
  537.                 2 merge passes
  538.               2.4 average passes over data
  539.  
  540.              2:51 elapsed time
  541.        -----------------------------------------------------------------
  542.  
  543.        The first two numbers are self-explanatory.  The next two are the
  544.        number of  times two  records were compared during the sort phase
  545.        and the  merge phase  respectively, followed by the total compar-
  546.        isons.
  547.  
  548.        The next  number is  total comparisons  divided by  the number of
  549.        records in the input file.  If there is no merge phase, this num-
  550.        ber is  typically 10  to 12.   If the file is large enough to re-
  551.        quire merging,  it is 12 to 20, on average.  If it is much larger
  552.        than 20,  it usually  means that there is something unusual about
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.        QSORT Text Sorting Utility                                 Page 7
  563.        QSORT Text Sorting Utility                                 Page 7
  564.  
  565.  
  566.        your input file.  It may already be sorted, or there may be large
  567.        blocks of  records which  compare equal.   This can happen if you
  568.        sort on, say column 50 and the input file contains a large number
  569.        of records  shorter than 50 bytes. In this case, a minor sort key
  570.        at column 1 may significantly speed sorting.
  571.  
  572.        The next  two items  are self-explanatory.   "Average passes over
  573.        data" reflects the number of times each record was read and writ-
  574.        ten.   For short  files not  requiring a  merge pass, this number
  575.        will be  1.0.  When merging is needed, the last merge pass is the
  576.        one which writes the output file and it must read and write every
  577.        record exactly  once.   Thus when  only one  merge pass  is made,
  578.        there will  be exactly  2.0 "average  passes over  data." In  the
  579.        above case  the first  merge pass  processed  about  40%  of  the
  580.        records, hence the value of 2.4.
  581.  
  582.        The above sort was performed on an Zenith 248, an eight megahertz
  583.        AT clone  with two  hard drives (C and D).  The input file was on
  584.        C; the  temporary merge  files were  placed on  D; and the output
  585.        file was  written to C.  The sort of a 1.3 megabyte file took un-
  586.        der three  minutes.   The same  sort on  an XT  should take about
  587.        seven minutes.
  588.  
  589.        The optional  subparameter, [V]  (for verbose),  causes the QSORT |
  590.        program to  make running progress reports to the screen, as well. |
  591.        Each pass during both the sort phase and the merge phase (if any) |
  592.        issues a  1-line report  telling the merge file(s) and the number |
  593.        of records  being processed during that particular pass.  This is |
  594.        not terribly useful for short files, but for the big ones, it can |
  595.        give the  user a warm comfortable feeling that something is actu- |
  596.        ally being done.                                                  |
  597.  
  598.        The /? Parameter
  599.        The /? Parameter
  600.  
  601.        The /?  parameter requests  help or  parameter evaluation.   When
  602.        QSORT is  executed with  the /? parameter alone, it lists a short
  603.        description of  the QSORT parameters.  If /? is entered as one of
  604.        several parameters,  QSORT will  produce a  short report  on  the
  605.        screen describing the sort it would perform based on those param-
  606.        eters without actually doing a sort.
  607.  
  608.        For example:
  609.  
  610.             QSORT /? /L5:12 /-3:2 /22 /T /R <INFILE.TXT >OUTFILE.TXT
  611.             QSORT /? /L5:12 /-3:2 /22 /T /R <INFILE.TXT >OUTFILE.TXT
  612.  
  613.        requests a  sort on  a file  of tagged records.  It defines three
  614.        sort keys,  one of  them inverted (-).  The /R parameter reverses
  615.        the sense  of all  three keys.   Since  redirection is specified,
  616.        QSORT does  not see  or know about the names of the files it will
  617.        sort.   The /?  parameter requests  a report, rather than a sort,
  618.        and QSORT obligingly produces on the screen, the following:
  619.  
  620.  
  621.  
  622.  
  623.  
  624.  
  625.  
  626.  
  627.  
  628.  
  629.  
  630.  
  631.        QSORT Text Sorting Utility                                 Page 8
  632.        QSORT Text Sorting Utility                                 Page 8
  633.  
  634.  
  635.        -----------------------------------------------------------------
  636.        QSORT - Text Sort - Version 3.20                                  |
  637.        Copyright (c) 1985, 1986, 1987  - Ben Baker - All rights reserved
  638.  
  639.        With the present arguments, QSORT would sort from STDIN to STDOUT
  640.        Records are multiple lines ending with an empty line
  641.  
  642.        Key fields in descending order of importance are:
  643.          Field  Pos   Len Type
  644.  
  645.              1    5    12 Lexical Descending
  646.              1    3     2 ASCII
  647.              1   22 65535 ASCII   Descending
  648.        -----------------------------------------------------------------
  649.  
  650.        The third  key has  an unspecified  length.   The  value  "65535"
  651.        merely means that this key extends to the end of each record.
  652.  
  653.        The /M<len>  supported in  earlier versions of QSORT is no longer
  654.        required, but  will be accepted (and ignored) by QSORT.  There is
  655.        no "hard-coded"  maximum record  length in  QSORT, but there is a
  656.        practical limit.  At some time during every sort, the two longest
  657.        records in  the input  file must be compared.  Therefore, the two
  658.        longest records  must be able to fit together in the sort buffer.
  659.        The sum  of their lengths cannot exceed about 50K -- not an alto-
  660.        gether unreasonable  limitation.   QSORT can  be shoe-horned into
  661.        tighter memory  and will  run if it can find 4K for a sort buffer
  662.        and 4K  for an  output buffer,  but the  two longest records must
  663.        still fit in the sort buffer together.
  664.  
  665.        Arguments may appear in any order on the command line except that
  666.        <in_file> must  appear before  <out_file>, and  /<key_spec> argu-
  667.        ments must appear in descending order of importance.
  668.  
  669.  
  670.  
  671.                                 Lexical Sorting
  672.                                 Lexical Sorting
  673.  
  674.  
  675.        The lexical  sorting capability  was borne  out of my own need to
  676.        sort word  lists with  mixed capitalization.  ASCII sequence pro-
  677.        duced some  bizarre results  when words beginning with 'Z' sorted
  678.        before those  beginning with 'a.' Case-insensitive sorting wasn't
  679.        much better because upper and lower case got mixed randomly.
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.        QSORT Text Sorting Utility                                 Page 9
  700.        QSORT Text Sorting Utility                                 Page 9
  701.  
  702.  
  703.        The following table will illustrate what I mean:
  704.  
  705.             INPUT         ASCII          CASE           LEXICAL
  706.                                       INSENSITIVE
  707.  
  708.             DeLaPort      Baker          Baker          Baker
  709.             Smith         Brown          brown          Brown
  710.             brown         DeAngelo       bRown          bRown
  711.             deLaPorte     DeLaPort       Brown          brown
  712.             Deangelo      Deangelo       Deangelo       DeAngelo
  713.             deAngelo      Deangelo       deangelo       Deangelo
  714.             Brown         DelaPort       Deangelo       Deangelo
  715.             smith         DelaPorte      deAngelo       deAngelo
  716.             delaPorte     Harry          DeAngelo       deangelo
  717.             DelaPort      Smith          delaPort       DeLaPort
  718.             DeAngelo      bRown          DelaPort       DelaPort
  719.             DelaPorte     brown          delaPort       delaPort
  720.             deangelo      deAngelo       DeLaPort       delaPort
  721.             Harry         deLaPorte      DelaPorte      DelaPorte
  722.             delaPort      deLaPorte      deLaPorte      deLaPorte
  723.             Baker         deangelo       delaPorte      deLaPorte
  724.             deLaPorte     delaPort       deLaPorte      delaPorte
  725.             Deangelo      delaPort       Harry          Harry
  726.             bRown         delaPorte      smith          Smith
  727.             delaPort      smith          Smith          smith
  728.  
  729.        The first column is a list of names in arbitrary order.  The sec-
  730.        ond is  an ASCII  sort of  that list.  Third we have one possible
  731.        case-insensitive sort  of the  list.  The fourth column is what I
  732.        really wanted.   It is sorted the way these words would be sorted
  733.        in a  dictionary (or lexicon).  The third and fourth columns both
  734.        collect words  of identical  spellings together, but in the third
  735.        column, upper  and lower  case spellings  are in arbitrary order,
  736.        while the  fourth column  places upper  case spellings  ahead  of
  737.        lower case spellings.
  738.  
  739.        For example, the two occurrences of Smith are widely separated in
  740.        column 2 because one is capitalized and the other is not.  Column
  741.        3 brings  the two  together, but  in the wrong order.  They might
  742.        have been  in the  right order,  but the  order is strictly arbi-
  743.        trary.   In column 4, Smith comes before smith, and lexical sort-
  744.        ing will always put them in this order.
  745.  
  746.        Lexical sorting  is achieved  by making  case-insensitive compar-
  747.        isons of  entire keys.   If the keys compare equal, an ASCII com-
  748.        parison is  made  to  arbitrate  ties.    In  other  words,  when
  749.        "lexical" keys in two records have different spellings, the case-
  750.        insensitive comparison determines the order of the records.  When
  751.        "lexical" keys  are spelled the same, the case-sensitive compari-
  752.        son determines the order of the records.
  753.  
  754.        Lexical keys are defined, as indicated above, by placing the let-
  755.        ter 'L'  immediately following  the slant-bar  (/) in  <key_spec>
  756.        definitions.
  757.  
  758.  
  759.  
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.        QSORT Text Sorting Utility                                Page 10
  767.        QSORT Text Sorting Utility                                Page 10
  768.  
  769.  
  770.        Lexical sorting can be very useful when needed, but be aware that
  771.        unnecessarily specifying lexical ordering may degrade performance
  772.        of QSORT.
  773.  
  774.  
  775.  
  776.                                    Examples
  777.                                    Examples
  778.  
  779.  
  780.        Produce a  sorted directory listing and display it on the console
  781.        a screen's worth at a time:
  782.  
  783.             A>DIR | QSORT | MORE
  784.             A>DIR | QSORT | MORE
  785.  
  786.        This demonstrates the use of QSORT as a "filter" in a "pipe."
  787.  
  788.  
  789.  
  790.        Produce a directory listing sorted by creation date and time, and
  791.        display it on the console a screen's worth at a time:
  792.  
  793.             A>DIR | QSORT /30:2 /24:5 /39 /34:5 | MORE
  794.             A>DIR | QSORT /30:2 /24:5 /39 /34:5 | MORE
  795.  
  796.        The output  of the  DIR command  is piped to QSORT.  The keys de-
  797.        fined are,  from left to right (major to minor), year (2 digits),
  798.        month and  day, AM/PM flag and time.  The output of QSORT is then
  799.        piped to MORE for display.
  800.  
  801.  
  802.  
  803.        Next, replace  the unsorted FILE.TXT with the same data sorted in
  804.        reverse order.  Use columns 10 to 16 as the sort key:
  805.  
  806.             >QSORT FILE.TXT /-10:7
  807.             >QSORT FILE.TXT /-10:7
  808.  
  809.                  or
  810.                  or
  811.  
  812.             A>QSORT FILE.TXT /10:7 /R
  813.             A>QSORT FILE.TXT /10:7 /R
  814.  
  815.                  or (SORT compatible)
  816.                  or (SORT compatible)
  817.  
  818.             A>QSORT FILE.TXT /R /+10
  819.             A>QSORT FILE.TXT /R /+10
  820.  
  821.        Next, perform a simple sort on a file with up to 240-byte records
  822.  
  823.             A>QSORT LARGE.REC /M240
  824.             A>QSORT LARGE.REC /M240
  825.  
  826.                  or
  827.                  or
  828.  
  829.             A>QSORT LARGE.REC
  830.             A>QSORT LARGE.REC
  831.  
  832.        Note that  the "/M240"  parameter is  no  longer needed, but will
  833.        not hurt.
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.        QSORT Text Sorting Utility                                Page 11
  845.        QSORT Text Sorting Utility                                Page 11
  846.  
  847.  
  848.  
  849.  
  850.        GLOSS.TXT is  an unsorted  glossary of terms.  The term being de-
  851.        fined by  each entry  appears first, followed by several lines of
  852.        definition.   The entries  are separated by empty lines.  Produce
  853.        GLOSS.SRT, a sorted version of the glossary:
  854.  
  855.             A>QSORT /T  <GLOSS.TXT >GLOSS.SRT      (with redirection)
  856.             A>QSORT /T  <GLOSS.TXT >GLOSS.SRT      (with redirection)
  857.  
  858.                  or
  859.                  or
  860.  
  861.             A>QSORT /T   GLOSS.TXT  GLOSS.SRT      (without redirection)
  862.             A>QSORT /T   GLOSS.TXT  GLOSS.SRT      (without redirection)
  863.  
  864.  
  865.  
  866.        A lawyer  keeps a  running log  of  his  billable  activities  in
  867.        TIME.LOG.   The first  line of  each entry is "mm/dd/yy hh:mm ac-
  868.        count#." He  always places  a tilde  (~) in the last line of each
  869.        entry.   He wishes  to sort the log by account number, and by as-
  870.        cending date and time within each account:
  871.  
  872.             A>QSORT  /16:7 /7:2 /1:5 /10:5 /T~  TIME.LOG
  873.             A>QSORT  /16:7 /7:2 /1:5 /10:5 /T~  TIME.LOG
  874.  
  875.  
  876.  
  877.        The directory  of users  for a bulletin board system is kept in a
  878.        binary file  of fixed-length  records 180  bytes long.   The user
  879.        name is  a 26-character field beginning in the first position and
  880.        the city/state  field is  a 16-character  field beginning  in the
  881.        fortieth position.  Sort the file by city/state and name.
  882.  
  883.             C>QSORT /F180 /40:16 /1:26 USER.BBS
  884.             C>QSORT /F180 /40:16 /1:26 USER.BBS
  885.  
  886.  
  887.  
  888.        DB.TXT is  a delimited  field output  file from  dBASE III,  Each
  889.        record contains  7 fields, delimited by commas.  Sort the file to
  890.        the screen using field 3 as a sort key.
  891.  
  892.             C>QSORT /D7 /3. <DB.TXT
  893.             C>QSORT /D7 /3. <DB.TXT
  894.  
  895.        Here, "standard input" has been redirected to the file.  Since no
  896.        redirection is  given for  "standard output,"   DOS assigns it to
  897.        the console by default.  This is NOT a sort-in-place!"
  898.  
  899.  
  900.  
  901.        You have  received a member list from the Society of End-users of
  902.        XENIX (SEX.LST).   Sort  the list by special interest (10 columns
  903.        beginning at 70) and name (30 columns beginning at 1).  Note that
  904.        the file  contains no  carriage return characters.  Since SEX.LST |
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.        QSORT Text Sorting Utility                                Page 12
  918.        QSORT Text Sorting Utility                                Page 12
  919.  
  920.  
  921.        is a  very large  file, we  wish to obtain running status reports |
  922.        and a final statistics report.                                    |
  923.  
  924.             C>QSORT  SEX.LST /70:10 /1:30 /D,\L /SV                      |
  925.             C>QSORT  SEX.LST /70:10 /1:30 /D,\L /SV
  926.  
  927.        The /D  parameter is  used to  redefine the newline sequence as a
  928.        naked line feed character.
  929.  
  930.  
  931.  
  932.        The file  LABEL.TXT contains mailing label images.  Each label is
  933.        6 lines  (1 inch)  high.  Line six is always empty and line three
  934.        is frequently  empty.  An extended Zip code always begins in col-
  935.        umn 20  of line  5, and extends to the end of the line.  In order
  936.        to take  advantage of  bulk mailing  rates, the  labels  must  be
  937.        sorted into carrier route (CRT) order.
  938.  
  939.             QSORT LABEL.TXT /5.20 /D6\N
  940.             QSORT LABEL.TXT /5.20 /D6\N
  941.  
  942.        We must  use a "delimited field" sort rather than a "tagged line"
  943.        sort for  two reasons:   1)  Line six is empty, not tagged with a
  944.        special character.   When  line three is also empty a label would
  945.        be broken  into two  pieces and separated by the sorting process.
  946.        2) Our  sort key is not at any known offset from the beginning of
  947.        the label.  Its position is fixed only relative to line five.
  948.  
  949.  
  950.  
  951.                         Error Messages and Return Codes                  |
  952.                         Error Messages and Return Codes
  953.  
  954.  
  955.        The QSORT program can encounter a number of different errors dur- |
  956.        ing execution.   Each will generate a brief error message on your |
  957.        console.   This section will attempt to list the messages you may |
  958.        see, and  give you  a little more detailed information about what |
  959.        might have caused the problem.                                    |
  960.  
  961.        Command Line Errors                                               |
  962.        Command Line Errors
  963.  
  964.        The most  common causes  of error messages are errors in the com- |
  965.        mand line  parameters.  Particularly when using a complicated set |
  966.        of keys,  I recommend  the use of "/?" as the last parameter.  If |
  967.        QSORT discovers an error, it will be reported.  the QSORT program |
  968.        will also  show you exactly what it would have done, had the "/?" |
  969.        parameter not been there, but will NOT perform a sort.            |
  970.  
  971.        You may then hit the "F3" key to recall the command, edit any bat |
  972.        parameters using the left and right cursor keys and the "INS" and |
  973.        "DEL" keys.   When  the command parses without error, and the re- |
  974.        port looks  like the  kind of sort you wish to make, hit the "F#" |
  975.        key once  more, then back space over the "/?" parameter, then hit |
  976.        "Enter" and QSORT will do the rest.                               |
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.        QSORT Text Sorting Utility                                Page 13
  989.        QSORT Text Sorting Utility                                Page 13
  990.  
  991.  
  992.        A frequent  cause of  command line  errors is the use of multiple |
  993.        parameters without  separating them  with spaces.    "/5:3/S"  is |
  994.        wrong.  "/5:3 /S" is right.                                       |
  995.  
  996.        One or  more of  the following errors might be encountered in the |
  997.        command line:                                                     |
  998.  
  999.             Three file names specified                                   |
  1000.             Three file names specified
  1001.  
  1002.        At most,  only two  file names may be given, an input file and an |
  1003.        output file.  The most likely cause of this message is forgetting |
  1004.        to use  the "/" character at the beginning of a key spec or other |
  1005.        parameter.                                                        |
  1006.  
  1007.             Invalid command line parameter "<parameter>"                 |
  1008.             Invalid command line parameter "<parameter>"
  1009.  
  1010.        This message  is issued if QSORT receives a parameter it does not |
  1011.        understand.   It is  usually a typographic error.  You meant "/D" |
  1012.        and hit "/E" by mistake.  The message displays the actual parame- |
  1013.        ter it did not understand.                                        |
  1014.  
  1015.             /D, /F and /T parameters are incompatible                    |
  1016.             /D, /F and /T parameters are incompatible
  1017.  
  1018.        Each of the above parameters tells QSORT to use a different scan- |
  1019.        ning routine  to parse  records.  Since only one such routine can |
  1020.        be used, it is an error to use more than one of these parameters. |
  1021.        In those  unusual situations where more than one might apply, use |
  1022.        the most  efficient one.   (The  order of  the parameters in this |
  1023.        message is  from most efficient to least efficient.  See the sec- |
  1024.        tion on  "Performance and  Input Record  Type" for  more informa- |
  1025.        tion.)                                                            |
  1026.  
  1027.             Multiple /<parameter> parameters encountered                 |
  1028.             Multiple /<parameter> parameters encountered
  1029.  
  1030.        This message  again applies  to the /D, /F and /T parameters.  In |
  1031.        this case, the same parameter appears twice in the command line.  |
  1032.  
  1033.             /F<length> parameter with invalid <length>                   |
  1034.             /F<length> parameter with invalid <length>
  1035.  
  1036.        No substitution  is made for "<length>" in this message.  This is |
  1037.        the actual  message displayed.  It means that either there was no |
  1038.        length specified, or the specified length was zero.               |
  1039.  
  1040.             Keyfield "<key_spec>" begins beyond end of record            |
  1041.             Keyfield "<key_spec>" begins beyond end of record
  1042.  
  1043.             Keyfield "<key_spec>" extends beyond end of record           |
  1044.             Keyfield "<key_spec>" extends beyond end of record
  1045.  
  1046.        These two messages refer to fixed-length records.  A key specifi- |
  1047.        cation has  told QSORT  that data exists beyond the bounds of the |
  1048.        record.   For instance,  suppose that  /F20 has  been  specified. |
  1049.        Then /23  would invoke  the first  message because  the record is |
  1050.        only 20  characters long.   Similarly /18:5 begins before the end |
  1051.        of the  record but extends beyond it, and would invoke the second |
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.        QSORT Text Sorting Utility                                Page 14
  1063.        QSORT Text Sorting Utility                                Page 14
  1064.  
  1065.  
  1066.        message.   Note that  /18 is  OK.   QSORT will assume a length of |
  1067.        three in this case.                                               |
  1068.  
  1069.             Invalid delimited field specification - "<key_spec>"         |
  1070.             Invalid delimited field specification - "<key_spec>"
  1071.  
  1072.        This one is similar to the previous messages.  The "field number" |
  1073.        portion of  a key specification was greater than the defined num- |
  1074.        ber of fields.  For example "/D5 /6.1:3" would provoke QSORT into |
  1075.        issuing this  message.   It's hard  to find  field 6 in a 5-field |
  1076.        record.                                                           |
  1077.  
  1078.             ABORT -- Error(s) in command line parameter(s)               |
  1079.             ABORT -- Error(s) in command line parameter(s)
  1080.  
  1081.        If any  of the  above messages are issued, QSORT will continue to |
  1082.        scan the command line and evaluate the parameters, but will even- |
  1083.        tually issue this message too.  If there are command line errors, |
  1084.        QSORT will NOT guess about your data.  It will stop!              |
  1085.  
  1086.        Memory Errors                                                     |
  1087.        Memory Errors
  1088.  
  1089.             ABORT -- Buffer allocation error                             |
  1090.             ABORT -- Buffer allocation error
  1091.  
  1092.        An error  of unknown origin occurred when QSORT was trying to al- |
  1093.        locate memory  for its  buffers.  The most likely cause here is a |
  1094.        "memory poor"  condition caused  by a too small partition under a |
  1095.        multitasker such  as DoubleDOS,  or perhaps  too many "terminate- |
  1096.        and-stay-resident" programs.   As an absolute minimum, QSORT must |
  1097.        be able  to obtain  eight kilobytes  of contiguous memory for its |
  1098.        sort buffer.                                                      |
  1099.  
  1100.             ABORT -- Insufficient memory                                 |
  1101.             ABORT -- Insufficient memory
  1102.  
  1103.        This one  can occur at any time during the sort.  QSORT must have |
  1104.        a sort buffer large enough to hold the two largest records in the |
  1105.        file.  Typically, the sort buffer is about fifty kilobytes, which |
  1106.        means that  if records  are shorter  than about twenty five kilo- |
  1107.        bytes, QSORT can usually handle them.  This is normally a problem |
  1108.        only when using the /T parameter.                                 |
  1109.  
  1110.        I/O Errors                                                        |
  1111.        I/O Errors
  1112.  
  1113.             ABORT -- Unable to open "<file_spec> for input"              |
  1114.             ABORT -- Unable to open "<file_spec> for input"
  1115.  
  1116.        QSORT  was   attempting  to  open  <file_spec>  for  input.    If |
  1117.        <file_spec> is your input file, you probably misspelled the name. |
  1118.        If <file_spec>  has the  form "number.SRT" QSORT could not find a |
  1119.        merge file  it thought  it had  created.  If this happens you may |
  1120.        have discovered a bug.  Please send me full particulars ASAP!     |
  1121.  
  1122.             ABORT -- Unable to create "<file_spec>" for output           |
  1123.             ABORT -- Unable to create "<file_spec>" for output
  1124.  
  1125.        QSORT was attempting to open <file_spec> for output, and the open |
  1126.        operation failed.   The  most likely cause is that you ran out of |
  1127.        disk space,  and DOS was unable to expand a subdirectory.  A root |
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135.  
  1136.  
  1137.        QSORT Text Sorting Utility                                Page 15
  1138.        QSORT Text Sorting Utility                                Page 15
  1139.  
  1140.  
  1141.        directory cannot  be expanded, and you may have run out of direc- |
  1142.        tory space.                                                       |
  1143.  
  1144.             ABORT -- Error reading input or merge file                   |
  1145.             ABORT -- Error reading input or merge file
  1146.  
  1147.        The section  of the  program which  issues this  message does not |
  1148.        know the  file name, so cannot help you much there.  This message |
  1149.        may mean  that your disk has a sector going bad.  (Well, it can't |
  1150.        all be good news!)                                                |
  1151.  
  1152.             ABORT -- Error writing to merge or output file               |
  1153.             ABORT -- Error writing to merge or output file
  1154.  
  1155.        This one  could also  mean a  bad sector,  but a  far more likely |
  1156.        cause is that you just ran out of disk space.                     |
  1157.  
  1158.        Internal Errors                                                   |
  1159.        Internal Errors
  1160.  
  1161.             ABORT -- Internal QSORT error                                |
  1162.             ABORT -- Internal QSORT error
  1163.  
  1164.        In theory,  this is  an error  which "can't happen."  If you EVER |
  1165.        get this  message, please  notify me  with as many details as you |
  1166.        can supply.   Actually I have NEVER seen this message issued by a |
  1167.        released version of QSORT.                                        |
  1168.  
  1169.        ERRORLEVEL Return Codes                                           |
  1170.        ERRORLEVEL Return Codes
  1171.  
  1172.        When QSORT  successfully completes a sort, it terminates with DOS |
  1173.        ERRORLEVEL set to zero. (See your DOS manual for more information |
  1174.        on ERRORLEVEL.)   If  it terminates for ANY other reason, it sets |
  1175.        ERRORLEVEL to  a non-zero  value, which  can be tested in a batch |
  1176.        file.   The following  are the  ERRORLEVEL codes  QSORT uses, and |
  1177.        their meanings:                                                   |
  1178.  
  1179.         Code     Meaning                                                 |
  1180.  
  1181.            0     Successful completion                                   |
  1182.            1     Command line error and/or "/?" parameter specified      |
  1183.            2     Open-for-read error                                     |
  1184.            3     Open-for-write error                                    |
  1185.            4     I/O error reading file                                  |
  1186.            5     I/O error writing file                                  |
  1187.            6     Memory error                                            |
  1188.          255     Internal error                                          |
  1189.  
  1190.  
  1191.  
  1192.  
  1193.  
  1194.  
  1195.  
  1196.  
  1197.  
  1198.  
  1199.  
  1200.  
  1201.  
  1202.  
  1203.  
  1204.  
  1205.  
  1206.  
  1207.  
  1208.  
  1209.        QSORT Text Sorting Utility                                Page 16
  1210.        QSORT Text Sorting Utility                                Page 16
  1211.  
  1212.  
  1213.                              Implementation Notes
  1214.                              Implementation Notes
  1215.  
  1216.  
  1217.        General Information
  1218.        General Information
  1219.  
  1220.        QSORT is intended as an enhanced replacement for DOS SORT.  It is
  1221.        nearly fully  upward compatible,  but provides  much more  flexi-
  1222.        bility.   Multiple sort  keys may be specified, a pseudo in-place
  1223.        sort may be performed and files and/or records of any size may be
  1224.        sorted provided only that there is sufficient disk space for work
  1225.        files and  the output  file.   QSORT uses  the "quick sort" algo-
  1226.        rithm, which cannot guarantee the order of records whose keys are
  1227.        all equal.   This  is the  one "incompatibility"  with DOS  SORT,
  1228.        which retains  the original  order of  records when  its only key
  1229.        compares equal.  This is important to SORT because it must be in-
  1230.        voked multiple  times to effect a multiple key sort.  With QSORT,
  1231.        you only sort once and there are usually enough keys available to
  1232.        insure you get the order you want the first time.
  1233.  
  1234.        QSORT uses  a sort  buffer of  about 50K  bytes and will fill the
  1235.        buffer as  full as  possible, and then sort its contents.  If the
  1236.        end of  the input  file has  been reached  and no  temporary work
  1237.        files have  been generated, the sorted contents of the buffer are
  1238.        written to the output file, completing the sort operation.
  1239.  
  1240.        If the  input file  is too  large to fit into the sort buffer, as
  1241.        much of  the input  file as  possible is  read into  the  buffer,
  1242.        sorted, then  written to  a temporary work file.  This process is
  1243.        repeated as  many times  as necessary to process the entire input
  1244.        file, each time creating a new work file for the sorted output.
  1245.  
  1246.        Upon completion  of the  "sort  phase,"  QSORT  begins  a  "merge
  1247.        phase."   Each work  file is  a sorted sub-set of the input file.
  1248.        Thus, work files may be read sequentially and combined to produce
  1249.        a sorted  output.  QSORT will open as many work files as DOS per-
  1250.        mits (more  on this  later).  If all the remaining work files can
  1251.        be opened,  the sorted  result is  written to  the  output  file.
  1252.        Otherwise, a new work file is created and another merge pass will
  1253.        be required.  On each merge pass, the number of work files is re-
  1254.        duced and  eventually all remaining work files will be opened and
  1255.        the sorted  output file will be written completing the sort oper-
  1256.        ation.
  1257.  
  1258.        Performance and DOS Configuration
  1259.        Performance and DOS Configuration
  1260.  
  1261.        QSORT is smart enough to never have just one work file remaining,
  1262.        which would  require an  unnecessary copy  operation.   In  fact,
  1263.        QSORT is  smarter than  just that  in its  handling of  the merge
  1264.        phase.   If more  than one  merge pass  is required, all the data
  1265.        merged during  the first  pass will  have to  be merged again, so
  1266.        QSORT attempts to minimize the first pass.  For example, if QSORT
  1267.        discovers it  may only  open 15 files at a time, and there are 16
  1268.        temporary files,  it will only merge two files on the first pass,
  1269.        creating a  17th file  as it  does.   Then in the second pass, it
  1270.  
  1271.  
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279.        QSORT Text Sorting Utility                                Page 17
  1280.        QSORT Text Sorting Utility                                Page 17
  1281.  
  1282.  
  1283.        will merge  all 15  remaining files to the output file.  The less
  1284.        data it processes twice, the faster it performs the sort!
  1285.  
  1286.        With nothing  else to  guide it, QSORT places its temporary files
  1287.        in the  default directory.  Either of two "environment variables"
  1288.        can override this.  (See your DOS manual for information on envi-
  1289.        ronment variables and the SET command.) The DOS command:
  1290.  
  1291.             SET QSTMP=<path>        or
  1292.             SET QSTMP=<path>        or
  1293.  
  1294.             SET TMP=<path>          or
  1295.             SET TMP=<path>          or
  1296.  
  1297.             SET TEMP=<path>
  1298.             SET TEMP=<path>
  1299.  
  1300.        will define  a path  for QSORT to use for its temporaries.  QSORT
  1301.        first looks  for the  environment variable QSTMP.  If it does not
  1302.        exist, QSORT  next looks  for TMP or TEMP in that order.  TMP and
  1303.        TEMP are  de facto  standards used by many programs, and are usu-
  1304.        ally defined in your AUTOEXEC.BAT batch file.  You might have TMP
  1305.        specifying a  64K RAM  disk to  speed up  your compiler.  In this
  1306.        case, an  attempt to  sort a  100K file  is  doomed  to  failure.
  1307.        Rather than  redefine TMP, you may define QSTMP to force QSORT to
  1308.        use some directory on your hard disk.  In fact:
  1309.  
  1310.             SET QSTMP=\
  1311.             SET QSTMP=\
  1312.  
  1313.        tells QSORT  to always  use the  root directory  of  the  default
  1314.        drive!
  1315.  
  1316.             CAUTION! The  root directory  has a  fixed size, and is      |
  1317.             CAUTION! The  root directory  has a  fixed size, and is
  1318.                  NOT expandable.  For a hard disk, it typically has      |
  1319.                  NOT expandable.  For a hard disk, it typically has
  1320.                  room for  only 512  file names,  less one for each      |
  1321.                  room for  only 512  file names,  less one for each
  1322.                  subdirectory and  one for  the  volume  label  (if      |
  1323.                  subdirectory and  one for  the  volume  label  (if
  1324.                  any).   Large files  may fail to sort if the QSORT      |
  1325.                  any).   Large files  may fail to sort if the QSORT
  1326.                  program must  place too many merge files in a root      |
  1327.                  program must  place too many merge files in a root
  1328.                  directory.  Subdirectories, on the other hand, are      |
  1329.                  directory.  Subdirectories, on the other hand, are
  1330.                  limited only by available disk space.                   |
  1331.                  limited only by available disk space.
  1332.  
  1333.        QSORT, to work properly, needs enough space on the output disk to
  1334.        hold the  output file.   Even  if the input file is to be deleted
  1335.        and resides  in the  same directory, that is not done until after
  1336.        the output file has been successfully written.  If one merge pass
  1337.        is required,  the disk space QSORT uses for temporary merge files
  1338.        will be  about 10%  larger than  the size  of the input file.  If
  1339.        more than  one merge pass will be required, allow about twice the
  1340.        size of the input file as temporary merge file space.
  1341.  
  1342.        One of  the advantages of controlling where QSORT places its tem-
  1343.        porary files  is to  insure adequate space for them.  A second is
  1344.        speed.   If the  temporary files can be placed on a separate disk
  1345.        from the  input and  output files,  disk seeking is minimized and
  1346.        performance improved.
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.        QSORT Text Sorting Utility                                Page 18
  1359.        QSORT Text Sorting Utility                                Page 18
  1360.  
  1361.  
  1362.        Each time  QSORT must create a new temporary merge file, the data
  1363.        put into  it will  be processed again.  Obviously, the more files
  1364.        QSORT can  open during  the merge  phase, the fewer times it will
  1365.        have to  handle each  record and  the faster  it can  sort  large
  1366.        files.   If DOS is properly pre-conditioned, QSORT can have up to
  1367.        15 temporary  merge files  open at once, and very large files can
  1368.        be sorted  with just  one sort pass and one merge pass.  Unfortu-
  1369.        nately, that capability is not automatic.
  1370.  
  1371.        DOS has  a fixed number of file "handles" that it associates with
  1372.        open files.   The  default number is eight, but DOS opens five of
  1373.        them for  standard input,  standard output, standard error, stan-
  1374.        dard printer  and standard  auxiliary device.   That leaves three
  1375.        for merging.   A  250K input  file would  produce five  temporary
  1376.        merge files  and that  would take  three merge  passes; merge two
  1377.        into one, leaving four; merge two into one leaving three; and fi-
  1378.        nally merge  three into  the output  file.  In the process, QSORT
  1379.        must read  and write about 80% of the file twice during the merge
  1380.        phase.
  1381.  
  1382.        Worse yet,  since you need at least three handles for merging, if
  1383.        you have  resident programs that have open files, you can't merge
  1384.        at all!
  1385.  
  1386.        DOS can  be told  to set aside more space for file handles.  Each
  1387.        handle is  only 39  bytes and  it's memory  very well spent.  One
  1388.        process can  have a  maximum of  20 handles open at one time, but
  1389.        since resident  processes may be using handles, I recommend 25 to
  1390.        35.  To do this, the root directory of the DISK OR DISKS YOU BOOT
  1391.        FROM must  contain a file named CONFIG.SYS.  If your boot disk(s)
  1392.        already contains  a CONFIG.SYS,  edit it, or if not, create it to
  1393.        contain the following line:
  1394.  
  1395.             FILES=25        (or more)
  1396.             FILES=25        (or more)
  1397.  
  1398.        While we're  at it,  let's add one more thing to CONFIG.SYS which
  1399.        will improve  the performance of QSORT and many other programs as
  1400.        well.  DOS provides, by default, two disk buffers.  These are the
  1401.        buffers it  uses to  do its  disk reads  and writes.   During the
  1402.        merge phase  QSORT may have many files open at once, reading from
  1403.        them in more or less random order.  DOS may have to read the same
  1404.        physical sector  several times  to get all its data.  But DOS can
  1405.        remember what's  in each  buffer and where it came from, and will
  1406.        not re-read  a sector  it already has in a buffer.  DOS needs 528
  1407.        bytes for each buffer.  I recommend 20 buffers to make QSORT per-
  1408.        form well  under the  most adverse conditions.  This will require
  1409.        an additional  9504 bytes  or slightly more than 9K, again memory
  1410.        well spent, so we add to CONFIG.SYS the following line:
  1411.  
  1412.             BUFFERS=20
  1413.             BUFFERS=20
  1414.  
  1415.        See your DOS manual for more information on CONFIG.SYS.
  1416.  
  1417.  
  1418.  
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425.  
  1426.  
  1427.        QSORT Text Sorting Utility                                Page 19
  1428.        QSORT Text Sorting Utility                                Page 19
  1429.  
  1430.  
  1431.        Performance and Input Record Type
  1432.        Performance and Input Record Type
  1433.  
  1434.        QSORT must  read and  parse logical  records before sorting them,
  1435.        then reassemble  them before  final output.   The type of records
  1436.        contained in  the file being sorted determines how much work this
  1437.        requires, and therefore has an impact on performance.
  1438.  
  1439.        The present version of QSORT can handle four record types: simple
  1440.        ASCII, tagged  ASCII, delimited field ASCII and fixed length, de-
  1441.        termined by  the presence  or absence of a /T, /D or /F parameter
  1442.        on the command line.
  1443.  
  1444.        Fixed length  records are very structured and require no parsing.
  1445.        Other things  equal, files  of fixed length records will sort the
  1446.        fastest.
  1447.  
  1448.        When parsing  simple ASCII  records, QSORT must find and mark the
  1449.        newline sequence,  then restore it for final output.  In general,
  1450.        this is relatively fast, but is affected by line length.  In par-
  1451.        ticular, lines  containing "over-strikes"  (naked  CR  characters
  1452.        followed by more data) can significantly slow down the parsing.
  1453.  
  1454.        Tagged ASCII  records are  parsed in  a fashion similar to simple
  1455.        ASCII records,  if a  tag character  is defined.   First  the tag
  1456.        character is  found, then  the next newline sequence is found and
  1457.        marked.   The time  required is  of course dependant on the total
  1458.        length of  the logical  record, but  is fairly  fast.   If no tag
  1459.        character is  defined, two  successive newline  sequences must be
  1460.        found.   This depends not only on total length, but the number of
  1461.        lines contained in a logical record.
  1462.  
  1463.        To parse  a delimited field record with n fields, n minus one de-
  1464.        limiters must be found and marked, then the newline sequence must
  1465.        be found and marked.  It is similar to tagged records with no de-
  1466.        fined tag character, but because records of this type are usually
  1467.        shorter than  tagged records, parsing delimited field records may
  1468.        be a  little faster.   It is certainly slower than parsing simple
  1469.        ASCII records.
  1470.  
  1471.        Performance and Sort Keys
  1472.        Performance and Sort Keys
  1473.  
  1474.        The sort  keys defined  on the command line have a lot to do with
  1475.        QSORT's performance.  There isn't much you can do in the way of a
  1476.        strategy you  can use when you need a particular file sorted in a
  1477.        particular way, but you should at least be aware.
  1478.  
  1479.        Several decisions  must be  made in comparing two records.  Which
  1480.        field contains the current key?  Is the field long enough to con-
  1481.        tain the  key in one, both or neither record?  Are the keys lexi-
  1482.        cal or  ASCII?   If the  answers to  any of  these questions will
  1483.        remain constant  over the  course of  a sort  run, they should be
  1484.        answered once, not several thousand times!
  1485.  
  1486.  
  1487.  
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.        QSORT Text Sorting Utility                                Page 20
  1497.        QSORT Text Sorting Utility                                Page 20
  1498.  
  1499.  
  1500.        QSORT has  ten record  comparison routines  varying in  degree of
  1501.        complexity.   At the  beginning of  each sort  run it selects the
  1502.        simplest one  possible, based on the parameters given, to be used
  1503.        throughout the run.
  1504.  
  1505.        If no sort key parameters are given, the entire record is used as
  1506.        a key.   The  compare routine has no decisions it must make -- it
  1507.        simply compares  the two  strings handed it.  This is the "simple
  1508.        sort," and is the fastest possible case.
  1509.  
  1510.        A sort  key that  does not  begin at  the beginning of a variable
  1511.        length record,  may not  be contained  in a  particular record at
  1512.        all, while  a fixed  length record  is known to contain all keys.
  1513.        Other things equal, files of fixed length records will sort some-
  1514.        what faster because the compare routine does not have to test for
  1515.        "key containment."
  1516.  
  1517.        Lexical keys  are first  compared with a "case insensitive" tech-
  1518.        nique.   Each character is tested to see if it is alphabetic.  If
  1519.        it is, it is converted to upper case.  Then a converted character
  1520.        from each  record is  tested.   This is obviously slower than di-
  1521.        rectly comparing  two characters.  In the event lexical keys com-
  1522.        pare equal,  they are compared again using a direct compare tech-
  1523.        nique!   Files with  lexical keys  sort slower than similar files
  1524.        without them.
  1525.  
  1526.        In the  case of  files with  delimited field records, the compare
  1527.        routine must  find the  correct field  for each key, determine if
  1528.        the keys  are contained  within the  fields, and  finally compare
  1529.        them.   The added  step of searching for fields slows record com-
  1530.        parison.
  1531.  
  1532.        In general, the more complex the data, the more complex the sort-
  1533.        ing task and the longer it will take.  QSORT attempts to optimize
  1534.        its performance  by making as many decisions as it can about your
  1535.        data up  front, then  selecting a compare routine that makes only
  1536.        the necessary decisions on a record-by-record basis.
  1537.  
  1538.        Performance and File Size
  1539.        Performance and File Size
  1540.  
  1541.        I received  a letter  from someone which included a graph showing
  1542.        QSORT's performance  in sorting  time vs.  file size.  He said he
  1543.        had expected  an exponential,  or at  least a  logarithmic curve.
  1544.        Instead time  increased linearly with file size.  I admit it puz-
  1545.        zled me  at the time, but Codeview, Microsoft's debugger, made it
  1546.        ease for  me to  measure the  performance of the various parts of
  1547.        the QSORT  program.  It turns out that actual sorting of data ac-
  1548.        counts for  a very  small percentage of QSORT's running time.  It
  1549.        spends most  of it's  time doing  I/O.   For files up to about 50
  1550.        kilobytes, it  will read and write each record once.  From 50K to
  1551.        about 750K  there will  be one merge pass and each record will be
  1552.        read and  written twice.   Since the amount of I/O increases lin-
  1553.        early over this range of file sizes, so will sorting time.
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.        QSORT Text Sorting Utility                                Page 21
  1565.        QSORT Text Sorting Utility                                Page 21
  1566.  
  1567.  
  1568.        Above about  750K a second merge pass will be needed, but in this
  1569.        size range,  only seven  to ten  percent of the data will be pro-
  1570.        cessed in  the first  merge pass,  so the sort time vs size curve
  1571.        will steepen  slightly, but  will not experience a large step (as
  1572.        it did  in versions  1 and  2).   Doubling the  file size  to 1.5
  1573.        megabytes should increase the sort time about three times.
  1574.  
  1575.        Sorting time  will be  approximately proportional  to  file  size
  1576.        times the  "average passes  over data" number from the statistics
  1577.        report.   Since this  number remains a constant "2.0" over a wide
  1578.        range of  file sizes,  sorting time  will be a linear function of
  1579.        file size in that range.
  1580.  
  1581.  
  1582.  
  1583.        I hope  you find  this program useful.  Your comments and sugges-
  1584.        tions are welcome.  My address is in the next section.
  1585.  
  1586.  
  1587.  
  1588.                                 About Shareware
  1589.                                 About Shareware
  1590.  
  1591.  
  1592.        QSORT is made available under the "shareware" concept.  Shareware
  1593.        products are distributed freely and publicly.  You are invited to
  1594.        "test drive"  them without  cost.  But shareware is NOT FREE!  If
  1595.        you use  a product,  you are  expected to  pay a fee for its use.
  1596.        Because overhead  costs are  minimal, this fee is usually a frac-
  1597.        tion of  the normal commercial price the product might carry, but
  1598.        it is NOT zero!
  1599.  
  1600.        If you find this program useful, you are asked to send its author
  1601.        a license  fee of $20 for each machine on which you use it.  This
  1602.        will encourage the development of other useful, affordable tools.
  1603.  
  1604.        QSORT may  be freely copied and distributed.  provided that 1) it
  1605.        is distributed  under the name "QSORT," and 2) this documentation
  1606.        file always  accompanies it.  Vendors wishing to distribute QSORT
  1607.        commercially, or  with commercial products may contact the author
  1608.        at the address below for terms.
  1609.  
  1610.        Send checks to:
  1611.  
  1612.                  Ben Baker                                               |
  1613.                  Baker's Acre                                            |
  1614.                  RR #1, Box 637                                          |
  1615.                  E. Alton, Il 62024                                      |
  1616.  
  1617.        Bug reports  or suggestions  may be  sent to the above address or |
  1618.        via electronic  mail to  FidoNet node  100/10  or  AlterNet  node |
  1619.        44/76,  or by logging into Baker's Acre BBS at 618-251-2169.      |
  1620.  
  1621.  
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.